#include <cstdio>
#include <iostream>
#include <iterator>
#include <memory>

#include "threadpool.h"

#if 0
// 测试Any类
#include "any.h"
int main() {
    auto f1 = []() -> Any { return 42; };
    auto f2 = []() -> Any { return std::string("Any"); };
    struct Foo {
        int a;
    };
    auto f3 = []() -> Any { return Foo{42}; };
    std::cout << f1().cast_<int>() << std::endl;
    std::cout << f2().cast_<std::string>() << std::endl;
    std::cout << f3().cast_<Foo>().a << std::endl;
}
#endif

#if 0
// 测试Semaphore类
#include <chrono>
#include <thread>

#include "semaphore.h"

int main() {
    Semaphore sema;
    bool ready = false;
    auto before = [&]() {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        ready = true;
        sema.post();
    };

    auto after = [&]() {
        sema.wait();
        std::cout << ready << std::endl;
    };

    std::thread t1(before);
    std::thread t2(after);
    t1.join();
    t2.join();
}
#endif

#include <iostream>
#include <thread>

#include "any.h"
#include "result.h"
#include "task.h"

class Worker : public Task {
public:
    Worker(int begin, int end) : begin_(begin), end_(end) {
    }

    Any run() {
        std::cout << "tid: " << std::this_thread::get_id() << "begin."
                  << std::endl;

        std::this_thread::sleep_for(std::chrono::seconds(4));
        using ull = unsigned long long;
        ull sum = 0;
        for (int i = begin_; i <= end_; ++i) {
            sum += i;
        }

        std::cout << "tid: " << std::this_thread::get_id() << "end."
                  << std::endl;
        return sum;
    }

private:
    int begin_;
    int end_;
};

int main() {
    {
        ThreadPool pool;
        pool.setMode(PoolMode::MODE_CACHED);
        pool.start(4);

        auto rs1 = pool.submit(std::make_shared<Worker>(1, 100000000));
        auto rs2 = pool.submit(std::make_shared<Worker>(100000001, 200000000));
        auto rs3 = pool.submit(std::make_shared<Worker>(200000001, 300000000));
        auto rs4 = pool.submit(std::make_shared<Worker>(1, 100000000));
        auto rs5 = pool.submit(std::make_shared<Worker>(1, 100000000));

        std::cout << rs1.get().cast_<unsigned long long>() +
                         rs2.get().cast_<unsigned long long>() +
                         rs3.get().cast_<unsigned long long>()
                  << std::endl;
    }
    getchar();
    return 0;
}
